home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fmt / RCS / fmt.c,v < prev    next >
Encoding:
Text File  |  1991-10-19  |  9.6 KB  |  481 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     91.10.18.21.23.14;  author rab;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     91.10.18.21.20.55;  author rab;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @@
  22.  
  23.  
  24. 1.2
  25. log
  26. @changed any() to strchr().
  27. @
  28. text
  29. @/*
  30.  * Copyright (c) 1980 Regents of the University of California.
  31.  * All rights reserved.
  32.  *
  33.  * Redistribution and use in source and binary forms are permitted
  34.  * provided that this notice is preserved and that due credit is given
  35.  * to the University of California at Berkeley. The name of the University
  36.  * may not be used to endorse or promote products derived from this
  37.  * software without specific prior written permission. This software
  38.  * is provided ``as is'' without express or implied warranty.
  39.  */
  40.  
  41. #ifndef lint
  42. char copyright[] =
  43. "@@(#) Copyright (c) 1980 Regents of the University of California.\n\
  44.  All rights reserved.\n";
  45. #endif /* not lint */
  46.  
  47. #ifndef lint
  48. static char sccsid[] = "@@(#)fmt.c    5.5 (Berkeley) 2/18/88";
  49. #endif /* not lint */
  50.  
  51. #include <stdio.h>
  52. #include <ctype.h>
  53.  
  54. /*
  55.  * fmt -- format the concatenation of input files or standard input
  56.  * onto standard output.  Designed for use with Mail ~|
  57.  *
  58.  * Syntax : fmt [ goal [ max ] ] [ name ... ]
  59.  * Authors: Kurt Shoens (UCB) 12/7/78;
  60.  *          Liz Allen (UMCP) 2/24/83 [Addition of goal length concept].
  61.  */
  62.  
  63. /* LIZ@@UOM 6/18/85 -- Don't need LENGTH any more.
  64.  * #define    LENGTH    72        Max line length in output
  65.  */
  66. #define    NOSTR    ((char *) 0)    /* Null string pointer for lint */
  67.  
  68. /* LIZ@@UOM 6/18/85 --New variables goal_length and max_length */
  69. int    goal_length = 65;    /* Target or goal line length in output */
  70. int    max_length = 75;    /* Max line length in output */
  71. int    pfx;            /* Current leading blank count */
  72. int    lineno;            /* Current input line */
  73. int    mark;            /* Last place we saw a head line */
  74.  
  75. char    *malloc();        /* for lint . . . */
  76. char    *headnames[] = {"To", "Subject", "Cc", 0};
  77.  
  78. /*
  79.  * Drive the whole formatter by managing input files.  Also,
  80.  * cause initialization of the output stuff and flush it out
  81.  * at the end.
  82.  */
  83.  
  84. main(argc, argv)
  85.     int argc;
  86.     char **argv;
  87. {
  88.     register FILE *fi;
  89.     register int errs = 0;
  90.     int number;        /* LIZ@@UOM 6/18/85 */
  91.  
  92.     setout();
  93.     lineno = 1;
  94.     mark = -10;
  95.     /*
  96.      * LIZ@@UOM 6/18/85 -- Check for goal and max length arguments 
  97.      */
  98.     if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
  99.         argv++;
  100.         argc--;
  101.         goal_length = number;
  102.         if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
  103.             argv++;
  104.             argc--;
  105.             max_length = number;
  106.         }
  107.     }
  108.     if (max_length <= goal_length) {
  109.         fprintf(stderr, "Max length must be greater than %s\n",
  110.             "goal length");
  111.         exit(1);
  112.     }
  113.     if (argc < 2) {
  114.         fmt(stdin);
  115.         oflush();
  116.         exit(0);
  117.     }
  118.     while (--argc) {
  119.         if ((fi = fopen(*++argv, "r")) == NULL) {
  120.             perror(*argv);
  121.             errs++;
  122.             continue;
  123.         }
  124.         fmt(fi);
  125.         fclose(fi);
  126.     }
  127.     oflush();
  128.     exit(errs);
  129. }
  130.  
  131. /*
  132.  * Read up characters from the passed input file, forming lines,
  133.  * doing ^H processing, expanding tabs, stripping trailing blanks,
  134.  * and sending each line down for analysis.
  135.  */
  136. fmt(fi)
  137.     FILE *fi;
  138. {
  139.     char linebuf[BUFSIZ], canonb[BUFSIZ];
  140.     register char *cp, *cp2;
  141.     register int c, col;
  142.  
  143.     c = getc(fi);
  144.     while (c != EOF) {
  145.         /*
  146.          * Collect a line, doing ^H processing.
  147.          * Leave tabs for now.
  148.          */
  149.         cp = linebuf;
  150.         while (c != '\n' && c != EOF && cp-linebuf < BUFSIZ-1) {
  151.             if (c == '\b') {
  152.                 if (cp > linebuf)
  153.                     cp--;
  154.                 c = getc(fi);
  155.                 continue;
  156.             }
  157.             if ((c < ' ' || c >= 0177) && c != '\t') {
  158.                 c = getc(fi);
  159.                 continue;
  160.             }
  161.             *cp++ = c;
  162.             c = getc(fi);
  163.         }
  164.         *cp = '\0';
  165.  
  166.         /*
  167.          * Toss anything remaining on the input line.
  168.          */
  169.         while (c != '\n' && c != EOF)
  170.             c = getc(fi);
  171.         
  172.         /*
  173.          * Expand tabs on the way to canonb.
  174.          */
  175.         col = 0;
  176.         cp = linebuf;
  177.         cp2 = canonb;
  178.         while (c = *cp++) {
  179.             if (c != '\t') {
  180.                 col++;
  181.                 if (cp2-canonb < BUFSIZ-1)
  182.                     *cp2++ = c;
  183.                 continue;
  184.             }
  185.             do {
  186.                 if (cp2-canonb < BUFSIZ-1)
  187.                     *cp2++ = ' ';
  188.                 col++;
  189.             } while ((col & 07) != 0);
  190.         }
  191.  
  192.         /*
  193.          * Swipe trailing blanks from the line.
  194.          */
  195.         for (cp2--; cp2 >= canonb && *cp2 == ' '; cp2--)
  196.             ;
  197.         *++cp2 = '\0';
  198.         prefix(canonb);
  199.         if (c != EOF)
  200.             c = getc(fi);
  201.     }
  202. }
  203.  
  204. /*
  205.  * Take a line devoid of tabs and other garbage and determine its
  206.  * blank prefix.  If the indent changes, call for a linebreak.
  207.  * If the input line is blank, echo the blank line on the output.
  208.  * Finally, if the line minus the prefix is a mail header, try to keep
  209.  * it on a line by itself.
  210.  */
  211. prefix(line)
  212.     char line[];
  213. {
  214.     register char *cp, **hp;
  215.     register int np, h;
  216.  
  217.     if (strlen(line) == 0) {
  218.         oflush();
  219.         putchar('\n');
  220.         return;
  221.     }
  222.     for (cp = line; *cp == ' '; cp++)
  223.         ;
  224.     np = cp - line;
  225.  
  226.     /*
  227.      * The following horrible expression attempts to avoid linebreaks
  228.      * when the indent changes due to a paragraph.
  229.      */
  230.     if (np != pfx && (np > pfx || abs(pfx-np) > 8))
  231.         oflush();
  232.     if (h = ishead(cp))
  233.         oflush(), mark = lineno;
  234.     if (lineno - mark < 3 && lineno - mark > 0)
  235.         for (hp = &headnames[0]; *hp != (char *) 0; hp++)
  236.             if (ispref(*hp, cp)) {
  237.                 h = 1;
  238.                 oflush();
  239.                 break;
  240.             }
  241.     if (!h && (h = (*cp == '.')))
  242.         oflush();
  243.     pfx = np;
  244.     split(cp);
  245.     if (h)
  246.         oflush();
  247.     lineno++;
  248. }
  249.  
  250. /*
  251.  * Split up the passed line into output "words" which are
  252.  * maximal strings of non-blanks with the blank separation
  253.  * attached at the end.  Pass these words along to the output
  254.  * line packer.
  255.  */
  256. split(line)
  257.     char line[];
  258. {
  259.     register char *cp, *cp2;
  260.     char word[BUFSIZ];
  261.     int wordl;        /* LIZ@@UOM 6/18/85 */
  262.  
  263.     cp = line;
  264.     while (*cp) {
  265.         cp2 = word;
  266.         wordl = 0;    /* LIZ@@UOM 6/18/85 */
  267.  
  268.         /*
  269.          * Collect a 'word,' allowing it to contain escaped white
  270.          * space. 
  271.          */
  272.         while (*cp && *cp != ' ') {
  273.             if (*cp == '\\' && isspace(cp[1]))
  274.                 *cp2++ = *cp++;
  275.             *cp2++ = *cp++;
  276.             wordl++;/* LIZ@@UOM 6/18/85 */
  277.         }
  278.  
  279.         /*
  280.          * Guarantee a space at end of line. Two spaces after end of
  281.          * sentence punctuation. 
  282.          */
  283.         if (*cp == '\0') {
  284.             *cp2++ = ' ';
  285.             if (strchr(".:!", cp[-1]))
  286.                 *cp2++ = ' ';
  287.         }
  288.         while (*cp == ' ')
  289.             *cp2++ = *cp++;
  290.         *cp2 = '\0';
  291.         /*
  292.          * LIZ@@UOM 6/18/85 pack(word); 
  293.          */
  294.         pack(word, wordl);
  295.     }
  296. }
  297.  
  298. /*
  299.  * Output section.
  300.  * Build up line images from the words passed in.  Prefix
  301.  * each line with correct number of blanks.  The buffer "outbuf"
  302.  * contains the current partial line image, including prefixed blanks.
  303.  * "outp" points to the next available space therein.  When outp is NOSTR,
  304.  * there ain't nothing in there yet.  At the bottom of this whole mess,
  305.  * leading tabs are reinserted.
  306.  */
  307. char    outbuf[BUFSIZ];            /* Sandbagged output line image */
  308. char    *outp;                /* Pointer in above */
  309.  
  310. /*
  311.  * Initialize the output section.
  312.  */
  313. setout()
  314. {
  315.     outp = NOSTR;
  316. }
  317.  
  318. /*
  319.  * Pack a word onto the output line.  If this is the beginning of
  320.  * the line, push on the appropriately-sized string of blanks first.
  321.  * If the word won't fit on the current line, flush and begin a new
  322.  * line.  If the word is too long to fit all by itself on a line,
  323.  * just give it its own and hope for the best.
  324.  *
  325.  * LIZ@@UOM 6/18/85 -- If the new word will fit in at less than the
  326.  *    goal length, take it.  If not, then check to see if the line
  327.  *    will be over the max length; if so put the word on the next
  328.  *    line.  If not, check to see if the line will be closer to the
  329.  *    goal length with or without the word and take it or put it on
  330.  *    the next line accordingly.
  331.  */
  332.  
  333. /*
  334.  * LIZ@@UOM 6/18/85 -- pass in the length of the word as well
  335.  * pack(word)
  336.  *    char word[];
  337.  */
  338. pack(word,wl)
  339.     char word[];
  340.     int wl;
  341. {
  342.     register char *cp;
  343.     register int s, t;
  344.  
  345.     if (outp == NOSTR)
  346.         leadin();
  347.     /*
  348.      * LIZ@@UOM 6/18/85 -- change condition to check goal_length; s is the
  349.      * length of the line before the word is added; t is now the length
  350.      * of the line after the word is added
  351.      *    t = strlen(word);
  352.      *    if (t+s <= LENGTH) 
  353.      */
  354.     s = outp - outbuf;
  355.     t = wl + s;
  356.     if ((t <= goal_length) ||
  357.         ((t <= max_length) && (t - goal_length <= goal_length - s))) {
  358.         /*
  359.          * In like flint! 
  360.          */
  361.         for (cp = word; *cp; *outp++ = *cp++);
  362.         return;
  363.     }
  364.     if (s > pfx) {
  365.         oflush();
  366.         leadin();
  367.     }
  368.     for (cp = word; *cp; *outp++ = *cp++);
  369. }
  370.  
  371. /*
  372.  * If there is anything on the current output line, send it on
  373.  * its way.  Set outp to NOSTR to indicate the absence of the current
  374.  * line prefix.
  375.  */
  376. oflush()
  377. {
  378.     if (outp == NOSTR)
  379.         return;
  380.     *outp = '\0';
  381.     tabulate(outbuf);
  382.     outp = NOSTR;
  383. }
  384.  
  385. /*
  386.  * Take the passed line buffer, insert leading tabs where possible, and
  387.  * output on standard output (finally).
  388.  */
  389. tabulate(line)
  390.     char line[];
  391. {
  392.     register char *cp, *cp2;
  393.     register int b, t;
  394.  
  395.     /*
  396.      * Toss trailing blanks in the output line.
  397.      */
  398.     cp = line + strlen(line) - 1;
  399.     while (cp >= line && *cp == ' ')
  400.         cp--;
  401.     *++cp = '\0';
  402.     
  403.     /*
  404.      * Count the leading blank space and tabulate.
  405.      */
  406.     for (cp = line; *cp == ' '; cp++)
  407.         ;
  408.     b = cp-line;
  409.     t = b >> 3;
  410.     b &= 07;
  411.     if (t > 0)
  412.         do
  413.             putc('\t', stdout);
  414.         while (--t);
  415.     if (b > 0)
  416.         do
  417.             putc(' ', stdout);
  418.         while (--b);
  419.     while (*cp)
  420.         putc(*cp++, stdout);
  421.     putc('\n', stdout);
  422. }
  423.  
  424. /*
  425.  * Initialize the output line with the appropriate number of
  426.  * leading blanks.
  427.  */
  428. leadin()
  429. {
  430.     register int b;
  431.     register char *cp;
  432.  
  433.     for (b = 0, cp = outbuf; b < pfx; b++)
  434.         *cp++ = ' ';
  435.     outp = cp;
  436. }
  437.  
  438. /*
  439.  * Save a string in dynamic space.
  440.  * This little goodie is needed for
  441.  * a headline detector in head.c
  442.  */
  443. char *
  444. savestr(str)
  445.     char str[];
  446. {
  447.     register char *top;
  448.  
  449.     top = malloc(strlen(str) + 1);
  450.     if (top == NOSTR) {
  451.         fprintf(stderr, "fmt:  Ran out of memory\n");
  452.         exit(1);
  453.     }
  454.     strcpy(top, str);
  455.     return (top);
  456. }
  457.  
  458. /*
  459.  * Is s1 a prefix of s2??
  460.  */
  461. ispref(s1, s2)
  462.     register char *s1, *s2;
  463. {
  464.  
  465.     while (*s1++ == *s2)
  466.         ;
  467.     return (*s1 == '\0');
  468. }
  469. @
  470.  
  471.  
  472. 1.1
  473. log
  474. @Initial revision
  475. @
  476. text
  477. @d257 1
  478. a257 1
  479.             if (any(cp[-1], ".:!"))
  480. @
  481.